﻿namespace AnalyStock.DataManage;

internal interface IDownloadProgress
{
    CancellationToken Token { get; }
    bool IsBusy { get; }
    bool IsCancel { get; }
    void Cancel();
    void Report(string taskNo, int progressPercentage, string userState);
}

public class DownloadProgress : IDownloadProgress, IDisposable
{
    private CancellationTokenSource tokenSource;
    private SendOrPostCallback invokeHandlers;
    private MultitaskProgressEventArgs multiTaskArgs;
    private SynchronizationContext syncContext;
    // 是否已经释放资源的标志
    private bool disposed = false;
    public DownloadProgress()
    {
        syncContext = SynchronizationContext.Current ?? new SynchronizationContext();
        invokeHandlers = InvokeHandlers;
        tokenSource = new CancellationTokenSource();
        IsBusy = false;
    }

    public bool IsBusy { get; private set; }

    public bool IsCancel => tokenSource.IsCancellationRequested;

    public CancellationToken Token => tokenSource.Token;

    public void Cancel()
    {
        tokenSource?.Cancel();
        IsBusy = false;
        SetAppIsBusyOnBackground();
    }

    void IDownloadProgress.Report(string taskNo, int progressPercentage, string userState)
    {
        IsBusy = progressPercentage < 100; //设置进程执行繁忙状态，防止意外操作         
        multiTaskArgs.ChangeStateVal(taskNo, progressPercentage, userState);
        OnChangedEvent(ref multiTaskArgs);
        SetAppIsBusyOnBackground();
    }

    //设置后台执行标志，防止未执行完成时，系统关闭退出
    private void SetAppIsBusyOnBackground()
    {
        AnalyStock.DataManage.ApplicationParam.IsBusyOfBackgroundWorking = IsBusy;
    }

    public event EventHandler<MultitaskProgressEventArgs> ProgressChanged;

    private void OnChangedEvent(ref MultitaskProgressEventArgs e)
    {
        syncContext.Send(invokeHandlers, e);        //post
    }

    private void InvokeHandlers(object e)
    {
        ProgressChanged?.Invoke(this, (MultitaskProgressEventArgs)e);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // TODO: 释放托管状态(托管对象) 
                ProgressChanged = null;
                invokeHandlers = null;
                syncContext = null;
                multiTaskArgs = default;
            }
            // TODO: 释放未托管的资源(未托管的对象)并重写终结器
            // TODO: 将大型字段设置为 null
            tokenSource?.Dispose();
            tokenSource = null;

        }
        disposed = true;
    }
    // Public implementation of Dispose pattern callable by consumers.
    public void Dispose()
    {
        // 表示用户显示调用
        Dispose(true);
        // Take yourself off the Finalization queue
        // to prevent finalization code for this object
        // from executing a second time.
        // 由于用户是显示调用，所以资源释放不再由GC来完成
        GC.SuppressFinalize(this);
    }

}

public struct MultitaskProgressEventArgs //: EventArgs
{
    public int ProgressPercentage { get; private set; }

    public string UserState { get; private set; }

    public string TaskNo { get; private set; }

    public void ChangeStateVal(in string taskNo, in int progPercentage, in string userState)
    {
        TaskNo = taskNo;
        ProgressPercentage = progPercentage;
        UserState = userState;
    }
}